﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.WPF.Theme.Common
 * 唯一标识：604120a3-3700-4026-bebc-050fcf338494
 * 文件名：TouchEventCommands
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/9/25 14:38:49
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>



namespace Vampirewal.Core.WPF.Theme;

public static class VampirewalCoreEventCommands
{
    public static IEnumerable<IVampirewalCoreEventCommand> GetEvents(DependencyObject obj)
    {
        return (IEnumerable<IVampirewalCoreEventCommand>)obj.GetValue(EventsProperty);
    }

    public static void SetEvents(DependencyObject obj, IEnumerable<IVampirewalCoreEventCommand> value)
    {
        obj.SetValue(EventsProperty, value);
    }

    // Using a DependencyProperty as the backing store for Events.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EventsProperty =
        DependencyProperty.RegisterAttached("Events", typeof(IEnumerable<IVampirewalCoreEventCommand>), typeof(VampirewalCoreEventCommands), new PropertyMetadata(null,Callback));

    private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is IEnumerable eventCommands)
        {
            foreach (IVampirewalCoreEventCommand eventCommand in eventCommands)
            {
                if (!string.IsNullOrEmpty(eventCommand.EventName))
                {
                    EventInfo eventInfo = d.GetType().GetEvent(eventCommand.EventName);
                    if (eventInfo == null)
                    {
                        throw new Exception($"没有找到名称为{eventCommand.EventName}的事件");
                    }

                    var handler= CreateEventHandler(eventInfo.EventHandlerType, eventCommand,d);

                    eventInfo.AddEventHandler(d, handler);
                }
                else
                {
                    throw new Exception($"事件名不能为空");
                }
            }
        }
    }


    private static Delegate CreateEventHandler(Type eventHandlerType, IVampirewalCoreEventCommand eventCommand, DependencyObject d)
    {
        // 获取事件处理程序的签名
        var invokeMethod = eventHandlerType.GetMethod("Invoke");
        if (invokeMethod == null)
        {
            throw new Exception("无法获取事件处理程序的Invoke方法");
        }

        var parameters = invokeMethod.GetParameters();
        if (parameters.Length != 2)
        {
            throw new Exception("事件处理程序的签名不正确");
        }

        // 创建表达式树
        var senderParameter = System.Linq.Expressions.Expression.Parameter(parameters[0].ParameterType, "sender");
        var eventArgsParameter = System.Linq.Expressions.Expression.Parameter(parameters[1].ParameterType, "eventArgs");

        // 获取属性值
        var propertyInfo = d.GetType().GetProperty(eventCommand.ExcuteCommandParamterOfPropertyName);
        if (propertyInfo == null)
        {
            throw new Exception($"没有找到名称为{eventCommand.ExcuteCommandParamterOfPropertyName}的属性");
        }

        var propertyValue = System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression.Constant(d), propertyInfo);

        // 调用命令的Execute方法
        var executeMethod = typeof(ICommand).GetMethod("Execute", new[] { typeof(object) });
        if (executeMethod == null)
        {
            throw new Exception("无法获取Execute方法");
        }

        var commandExpression = System.Linq.Expressions.Expression.Constant(eventCommand.ExcuteCommand);

        var executeExpression = System.Linq.Expressions.Expression.Call(commandExpression, executeMethod, propertyValue);

        var lambda = System.Linq.Expressions.Expression.Lambda(eventHandlerType, executeExpression, senderParameter, eventArgsParameter);

        // 编译表达式树并创建委托
        return lambda.Compile();
    }


    //public static Dictionary<string, IVampirewalCoreEventCommand> Dic { get; set; } = new Dictionary<string, IVampirewalCoreEventCommand>();

}